﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Brjnk.CoordinateSystem2D.Layers
{
    internal class PhotoInternal
    {
        private static ImageSource multiImage;

        static PhotoInternal()
        {
            var uri = new Uri(@"pack://application:,,,/CoordinateSystem2D;Component/Images/photoGroup.png");
            BitmapImage icon = new BitmapImage();
            icon.BeginInit();
            icon.UriSource = uri;
            icon.EndInit();

            multiImage = icon;
        }

        private IPhoto photo;
        private Point transformed;
        private Point screenPosition;

        internal Image Image { get; private set; }

        internal Border Element { get; private set; }

        internal Point ScreenPosition { get { return screenPosition; } }

        internal Point TransformedPosition { get { return transformed; } }

        internal IPhoto Photo { get { return photo; } }

        internal PhotoInternal(IPhoto photo, ViewInfoBase view, Size renderSize)
        {
            this.photo = photo;
            Image = new Image();
            Image.IsHitTestVisible = false;
            Element = new Border();
            Element.Child = Image;
            Element.BorderThickness = new Thickness(3.5);
            Element.BorderBrush = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
            Image.Source = photo.Thumbnail;

            Brjnk.Common.UI.Canvas.SetCenterX(Element, new Brjnk.Common.UI.ElementCenter(true, false, 0.5));
            Brjnk.Common.UI.Canvas.SetCenterY(Element, new Brjnk.Common.UI.ElementCenter(true, false, 0.5));
            UpdateSize(renderSize);
            UpdateTransformed(view);
            UpdateRotation(photo.Orientation);
            UpdateVisibility();
        }

        #region Updating

        internal void UpdateTransformed(ViewInfoBase view)
        {
            if (view == null) return;
            this.transformed = view.Transform(photo.Position);
            UpdateScreenPosition(view);
        }

        internal void UpdateSize(Size renderSize)
        {
            Image.MaxWidth = renderSize.Width;
            Image.MaxHeight = renderSize.Height;
        }

        internal void UpdateScreenPosition(ViewInfoBase view)
        {
            this.screenPosition = view.FromInternalToRelative(this.transformed);
            Brjnk.Common.UI.Canvas.SetX(Element, this.screenPosition.X);
            Brjnk.Common.UI.Canvas.SetY(Element, this.screenPosition.Y);
        }

        internal void UpdateThumbnail()
        {
            if (groupedItems == null)
            {
                Image.Source = photo.Thumbnail;
            }
        }

        private bool shown = true;

        /// <summary>
        /// Zapne zobrazování fotografie (souvisí se seskupováním fotografií, nikoliv s IPhoto.IsVisible)
        /// </summary>
        internal void Show()
        {
            shown = true;
            RefreshVisibility();
        }

        /// <summary>
        /// Vypne zobrazování fotografie (souvisí se seskupováním fotografií, nikoliv s IPhoto.IsVisible)
        /// </summary>
        internal void Hide()
        {
            shown = false;
            RefreshVisibility();
        }

        private void RefreshVisibility()
        {
            bool visible = shown && photo.IsVisible;
            var v = visible ? Visibility.Visible : Visibility.Hidden;
            //nenastavovat pokud jsou stejný (výkonostní zrychlení)
            if (v != Element.Visibility) { Element.Visibility = v; }
        }

        internal void UpdateRotation(PhotoOrientation rotation)
        {
            if (groupedItems != null) return;
            double angle = 0;
            switch (rotation)
            {
                case PhotoOrientation.Clockwise90:
                    angle = 90;
                    break;

                case PhotoOrientation.Degrees180:
                    angle = 180;
                    break;

                case PhotoOrientation.Clockwise270:
                    angle = 270;
                    break;
            }
            Element.RenderTransform = new RotateTransform(angle);
            Element.RenderTransformOrigin = new Point(0.5, 0.5);
        }

        internal void UpdateVisibility()
        {
            RefreshVisibility();
        }

        #endregion Updating

        #region Grouping

        private List<PhotoInternal> groupedItems;
        private Comparison<IPhoto> comparsion;
        private bool ordered;

        internal void SetGroup(List<PhotoInternal> nearItems, Comparison<IPhoto> comparsion)
        {
            this.comparsion = comparsion;
            ordered = false;
            if (nearItems == null) throw new ArgumentNullException();
            groupedItems = nearItems;
            Image.Source = multiImage;
            Element.RenderTransform = null;
        }

        internal void ResetGroup()
        {
            if (groupedItems != null)
            {
                groupedItems = null;
                Image.Source = photo.Thumbnail;
                UpdateRotation(this.photo.Orientation);
            }
        }

        #endregion Grouping

        internal IList<PhotoInternal> GetAllPhotos()
        {
            if (groupedItems == null) return new List<PhotoInternal>(1) { this };
            else
            {
                if (!ordered && comparsion != null) groupedItems.Sort((x, y) => comparsion(x.Photo, y.Photo));
                return groupedItems;
            }
        }
    }
}